package jfreechart.tsp.arithmetic;

import java.util.ArrayList;
import java.util.List;

//解路径:在粒子群算法中相当于一个粒子
@SuppressWarnings("unchecked")
public class Tour {
    public ArrayList<City> cities = new ArrayList<City>();//当前解的城市列表
    double dist = 0;//当前个体的消耗

    //    粒子具有记忆功能
//    Tour best = null;//历史最优解
    ArrayList<City> best = new ArrayList<City>();//历史最优解的城市列表
    double bestDist = Double.MAX_VALUE;//个体的历史最优消耗

    double[][] distence;//缓存城市间距离矩阵

    public Tour() {
    };

    //构造 带初始化功能
    public Tour(ArrayList<City> cities, double[][] distence) {
        this.cities = (ArrayList) cities.clone();
        this.distence = distence;

//        Collections.shuffle(this.cities);//打乱顺序

        //初始化更新
        update();
    }

    //获取当前解的总消耗
    public double getDistence() {
        if (dist == 0) {
            int start = cities.get(0).idx;
            for (int i = 1; i < cities.size(); i++) {
                dist += distence[start][cities.get(i).idx];
                start = cities.get(i).idx;
            }
            dist += distence[start][cities.get(0).idx];//最后回到起点
        }
        return dist;
    }

    //交换两个城市
    public void swap(List<City> cities, int x, int y) {
        City tmp = cities.get(x);
        cities.set(x, cities.get(y));
        cities.set(y, tmp);
        dist = 0;//注意:需要重新初始化
    }

    //更新局部最优解操作
    public void update() {
        if (getDistence() < bestDist) {
            best = (ArrayList<City>) cities.clone();
            bestDist = getDistence();
        }
    }

    //获取城市索引
    private int getIdx(int start, List<City> cities, City city) {
        int idx = -1;
        for (int i = start; i < cities.size(); i++) {
            if (city.equals(cities.get(i))) {
                idx = i;
                break;
            }
        }
        return idx;
    }

    //定义粒子群算法中速度向量的  best[i]-X[i] 操作
    //返回与x的交换序
    //tour经过交换序SwapSequence交换后会转换成x
    public List<ParticleSwarm.SwapSequence> minus(ArrayList<City> x) {
        List<ParticleSwarm.SwapSequence> ss = new ArrayList<ParticleSwarm.SwapSequence>();
        List<City> tmp = (ArrayList<City>) cities.clone();
        int n;
        for (int i = 0; i < size(); i++) {
            if (!x.get(i).equals(tmp.get(i))) {//不相等,则找到城市x在当前tour的下标
                n = getIdx(i + 1, tmp, x.get(i));
                swap(tmp, i, n);
                ss.add(new ParticleSwarm.SwapSequence(i, n));
            }
        }
        return ss;
    }

    public void addCity(City city) {
        this.cities.add(city);
    }

    public City getCity(int x) {
        return cities.get(x);
    }

    public int size() {
        return cities.size();
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < cities.size(); i++) {
            sb.append("(" + cities.get(i).x + "," + cities.get(i).y + ")-->");
        }
        sb.append("(" + cities.get(0).x + "," + cities.get(0).y + ")");//最后回到起点
        return sb.toString();
    }

}
